#!/usr/bin/perl

package Swignition::Export::Point;
use Swignition::Export;
use JSON 2.0;

# Reference:
# http://www.ibiblio.org/hhalpin/homepage/notes/vcardtable.html
# (Though that page does contain a number of mistakes, such as equating a vCard
# "TITLE" [a job title] with a FOAF "title" [e.g. Mr, Mrs].)

sub is
{
	my $subject = shift;
	return unless ($subject);
	return unless (ref $subject eq 'Swignition::RDFModel::Subject');	
	return
		unless (defined $subject->property('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'));
	foreach my $Type ( @{$subject
		->property('http://www.w3.org/1999/02/22-rdf-syntax-ns#type')
		->valObjects} )
	{
		my $type = $Type->toString;
		return 1
			if (($type eq 'http://www.w3.org/2001/vcard-rdf/3.0#GEO')
			||  ($type eq 'http://www.w3.org/2006/vcard/ns#Location')
			||  ($type eq 'http://www.w3.org/2006/03/hcard#geo')
			||  ($type eq 'http://www.w3.org/2003/01/geo/wgs84_pos#Point')
			||  ($type eq 'urn:ietf:rfc:2426#Geo'));
	}
	return 1
		if (defined firstOf($subject,
			'http://www.w3.org/2003/01/geo/wgs84_pos#lat',
			'http://www.w3.org/2003/01/geo/wgs84_pos#long',
			'http://www.georss.org/georss/point',
			'http://www.w3.org/2006/vcard/ns#latitude',
			'http://www.w3.org/2006/vcard/ns#longitude',
			'http://www.w3.org/2006/03/hcard#latitude',
			'http://www.w3.org/2006/03/hcard#longitude',
			'urn:ietf:rfc:2426#latitude',
			'urn:ietf:rfc:2426#longitude'));
	return;
}

sub outputs
{
	return [
		{
			code  => 'VCFLine',
			name  => 'vCard-compatible Line',
			type  => 'text/x-directory-part'
		},
		{
			code  => 'Text',
			name  => 'Comma-separated coordinates',
			type  => 'text/plain',
			multi => 1
		},
		{
			code  => 'Text3',
			name  => 'Comma-separated coordinates (with altitude)',
			type  => 'text/plain',
			multi => 1
		},
		{
			code  => 'JSON',
			name  => 'jCard geo',
			type  => 'text/x-json',
			multi => 1
		}
	];
}

sub multiText
{
	my $triples = shift;
	my $rv = "latitude,longitude\r\n";
	foreach my $s (keys %$triples)
	{
		$rv .= outText($triples, $s) . "\r\n"
			if (defined $triples->{$s} && is($triples->{$s}));
	}
	return $rv;
}

sub outText
{
	my ($key, $coords) = outVCFLine(@_);
	$coords =~ s/\;/\,/;
	return $coords;
}

sub multiText3
{
	my $triples = shift;
	my $rv = "latitude,longitude,altitude\r\n";
	foreach my $s (keys %$triples)
	{
		$rv .= outText3($triples, $s) . "\r\n"
			if (defined $triples->{$s} && is($triples->{$s}));
	}
	return $rv;
}

sub outText3
{
	my $coords = outText(@_);

	my $alt  = firstOf($S, 'urn:ietf:rfc:2426#altitude',
		'http://www.w3.org/2003/01/geo/wgs84_pos#alt',
		'http://microformats.org/wiki/geo-extension-nonWGS84#altitude');
	$alt =~ s/[^0-9\.-]//g;
	
	return "$coords,$alt" if ($alt);
	return $coords;
}

sub _outJSON
{
	my $triples = shift;
	my $subject = shift;
	my $S = findSubject($triples, $subject);
	
	my $lat  = firstOfLiteral($S,
		['urn:ietf:rfc:2426#latitude',
		'http://www.w3.org/2003/01/geo/wgs84_pos#lat',
		'http://www.w3.org/2006/vcard/ns#latitude',
		'http://www.w3.org/2006/03/hcard#latitude',
		'http://microformats.org/wiki/geo-extension-nonWGS84#latitude'],
		['urn:ietf:rfc:2426#value',
		'http://www.w3.org/1999/02/22-rdf-syntax-ns#value']);
	my $long = firstOfLiteral($S,
		['urn:ietf:rfc:2426#longitude',
		'http://www.w3.org/2003/01/geo/wgs84_pos#long',
		'http://www.w3.org/2006/vcard/ns#longitude',
		'http://www.w3.org/2006/03/hcard#longitude',
		'http://microformats.org/wiki/geo-extension-nonWGS84#longitude'],
		['urn:ietf:rfc:2426#value',
		'http://www.w3.org/1999/02/22-rdf-syntax-ns#value']);
	my $alt = firstOfLiteral($S,
		['urn:ietf:rfc:2426#altitude',
		'http://www.w3.org/2003/01/geo/wgs84_pos#alt',
		'http://microformats.org/wiki/geo-extension-nonWGS84#altitude'],
		['urn:ietf:rfc:2426#value',
		'http://www.w3.org/1999/02/22-rdf-syntax-ns#value']);
	my $rf = firstOfLiteral($S,
		['http://microformats.org/wiki/geo-extension-nonWGS84#reference-frame'],
		['urn:ietf:rfc:2426#value',
		'http://www.w3.org/1999/02/22-rdf-syntax-ns#value']);
	my $body = firstOfLiteral($S,
		['http://microformats.org/wiki/geo-extension-nonWGS84#body'],
		['urn:ietf:rfc:2426#value',
		'http://www.w3.org/1999/02/22-rdf-syntax-ns#value']);

	my %rv;
	$rv{'latitude'} = $lat if (defined $lat);
	$rv{'longitude'} = $long if (defined $long);
	$rv{'altitude'} = $alt if (defined $alt);
	$rv{'reference-frame'} = $rf if (defined $rf);
	$rv{'body'} = $body if (defined $body);
	
	return %rv;
}


sub multiJSON
{
	my $triples = shift;
	my @rv;
	foreach my $s (keys %$triples)
	{
		if (defined $triples->{$s} && is($triples->{$s}))
		{
			my %r = _outJSON($triples, $s);
			push @rv, \%r;
		}
	}
 	return to_json(\@rv, {utf8 => 1, pretty => 1, canonical => 1})."\n";
}


sub outJSON
{
	my %json = _outJSON(@_);
 	return to_json(\%json, {utf8 => 1, pretty => 1, canonical => 1})."\n";
}


sub outVCFLine
{
	my $triples = shift;
	my $subject = shift;
	my $S = findSubject($triples, $subject);
	my $geo;
	
	my $lat  = firstOfLiteral($S,
		['urn:ietf:rfc:2426#latitude',
		'http://www.w3.org/2003/01/geo/wgs84_pos#lat',
		'http://www.w3.org/2006/vcard/ns#latitude',
		'http://www.w3.org/2006/03/hcard#latitude'],
		['urn:ietf:rfc:2426#value',
		'http://www.w3.org/1999/02/22-rdf-syntax-ns#value']);
	my $long = firstOfLiteral($S, 
		['urn:ietf:rfc:2426#longitude',
		'http://www.w3.org/2003/01/geo/wgs84_pos#long',
		'http://www.w3.org/2006/vcard/ns#longitude',
		'http://www.w3.org/2006/03/hcard#longitude'],
		['urn:ietf:rfc:2426#value',
		'http://www.w3.org/1999/02/22-rdf-syntax-ns#value']);
	
	if (length $lat && length $long)
	{
		$geo = "$lat;$long";
	}
	else
	{
		$geo = firstOfLiteral($S,
			['http://www.georss.org/georss/point'],
			['urn:ietf:rfc:2426#value',
			'http://www.w3.org/1999/02/22-rdf-syntax-ns#value']);
		
		if ($geo)
		{
			$geo =~ s/(^\s+|\s+$)//g;
			$geo =~ s/\s+/\;/;
		}
		else
		{
			$geo = $subject;
			$geo =~ /^geo\:([0-9\.]*),([0-9\.]*)/;
			$geo = "$1;$2";
		}
	}
	
	return ('GEO', $geo);
}

1;
